home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!zephyr.ens.tek.com!tekred!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v11i013: tinymud2 - user-extendible multi-user adventure (v1.5.4), Part09/10
- Message-ID: <6058@tekred.CNA.TEK.COM>
- Date: 30 Jul 90 16:46:44 GMT
- Sender: news@tekred.CNA.TEK.COM
- Lines: 2088
- Approved: billr@saab.CNA.TEK.COM
-
- Submitted-by: James Aspnes <asp@cs.cmu.edu>
- Posting-number: Volume 11, Issue 13
- Archive-name: tinymud2/Part09
- Supersedes: tinymud: Volume 8, Issue 80-83
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 9 (of 10)."
- # Contents: CHANGES compress.c create.c db.h match.c move.c
- # predicates.c speech.c
- # Wrapped by billr@saab on Fri Jul 27 15:27:50 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'CHANGES' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'CHANGES'\"
- else
- echo shar: Extracting \"'CHANGES'\" \(7507 characters\)
- sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
- X------------------------------------------------------------------------
- X
- XChanges in Islandia Version (1.5.4) by Fuzzy (Michael Mauldin)
- X
- X25-Jun-90 Allow people to drop exits they are carrying that
- X have location -1 (this fixes a problem with exits
- X that get recycled while they are carried).
- X
- X9-Jun-90 Added failure message for whispers to objects
- X Made DUMPCORE on error the default (writes DB,
- X then calls abort() with SIGILL enabled). Set
- X -DNODUMPCORE to inhibit core dumps.
- X Unified Islandia & TinyHELL sources, with switch
- X in config.h
- X Added Virus (Robert Hood's) port concentrator.
- X Added connect.txt, for messages before the connect.
- X
- X There are now 5 text files associated with TinyMUD:
- X connect.txt before logging in
- X motd.txt after logging in
- X tinker.txt after logging in for tinkers
- X news.txt News command
- X help.txt Help command
- X
- X17-Jun-90 Added Virus's concentrator code.
- X Fixed extract to allow player names instead of numbers,
- X and added special commands: reachable, players,
- X norecycle a<num> b<num>
- X
- X------------------------------------------------------------------------
- X
- XChanges in Islandia/Hell Version (1.5.3C) by Random (Russ Smith)
- X
- X5-Jun-90 Made ABODE govern dropto
- X Allow players to DARKen objects that they own and are
- X carrying, but not let them drop DARK objects in an
- X area they couldn't link to.
- X Added UNWANTED flag, which allows people to @chown
- X objects to themselves, subject to locking;
- X Made @chown understand 'me'
- X Made @recycle set its object to be UNWANTED
- X Made page and whisper check the WHO list and
- X respond appropriately.
- X
- X------------------------------------------------------------------------
- X
- XChanges in Islandia Version (1.5.3B) by Fuzzy (Michael Mauldin)
- X
- X31-May-90 Added casts to signal arguments to get rid of
- X annoying warnings from gcc.
- X
- X28-May-90 Added @count & @recycle...@count is redundant with
- X @stat for players, but it can also be run by
- X non-tinkers, and @count of a room summarizes
- X contents: a new feature. Note that @count is
- X less work than @find, because only the db array
- X is used, no strings are referenced.
- X
- X Also fixed bug in extract:
- X
- X extract all -<player>
- X
- X now extracts player and his contents...before,
- X a bug/feature/omission caused only the player
- X to be extracted.
- X
- X Syntax:
- X
- X @count <player>
- X @count <room>
- X
- X @recycle <thing> = <recipient>
- X @recycle <thing> defaults to Recycler.
- X
- X Recycling an object destroys its strings, and chowns
- X the object to a player called Recycler. The idea is
- X that periodically you can "extract all -<recycler-num>"
- X to remove the recycled objects.
- X
- X Added code to extract to check for isolated rooms
- X (no entrances, or no entrances, exits, or contents).
- X
- X Fixed bug/feature in extract that caused it to complain
- X aboute unlinked exits being carried by players. It no
- X longer complains about them.
- X
- X28-May-90 Added NOFAKES switch to forbid use of names that
- X are really first words from important system messages
- X (A, An, The, You, Your, Going, Huh?)
- X
- X25-May-90: Added code to @bobble to chown all the players
- X objects to another user.
- X
- X20-May-90: Added ROBOT flag...enables OUTPUTPREFIX/SUFFIX,
- X prevents ROBOT players from getting objects,
- X using exits, or entering rooms with ROBOT set.
- X
- X Changed Wizards to Tinkers, Temples to Junkpiles,
- X and 'sacrifice' to 'donate'. Added special
- X MOTD for Tinkers (file ../lib/tinker.txt).
- X
- X Also changed @toad to @bobble.
- X
- X Fixed problem with @link on links that are
- X set to *home*.
- X
- X Fixed security hole that allowed a Wizard to
- X @force God...thus preventing
- X
- X @force Wizard = @set *Apprentice = WIZARD
- X
- X Changed game.c so that on errors both a database
- X dump and a regular core dump are written.
- X
- X17-May-90: Fixed bug where @name guest = foo bar caused
- X a crash because guest has no password (file set.c)
- X
- X Added MOTD function, file ../lib/motd.txt
- X (files help.c, interface.c)
- X
- X Added caching of hostnames so that Tinkers can do a
- X WHO without bogging down the server.
- X
- X11-May-90 Added Random's "page <name> = <msg>" command, to allow
- X sending messages simply...people otherwise used
- X
- X @name me = <msg> / @page <name> / @name me = <desc>
- X
- X anyway, so why not make it easy.
- X
- X------------------------------------------------------------------------
- X
- XChanges in Firefoot version (1.5.3A) (Scott Goehring):
- X
- XAdded code to detach netmud from the terminal on startup (-DDETACH).
- X
- XNetmud now writes to a log file instead of stderr when detached.
- XSIGUSR2 will close and reopen the log file.
- X
- XSIGTERM and SIGINT now cause netmud to shutdown cleanly instead of
- Xpanicking (good for when your system is /etc/shutdown'd).
- X
- XAdded parallel compile support to the makefile (if you're on a
- XSequent, compile with 'make P=\&').
- X
- XLog file entries are now preceded by the time of day.
- X
- XThe status dumper (SIGUSR1) has been removed.
- X
- XAdded Random's preregistration support (disabled create, @pcreate).
- X
- XAdded OJ's examine hack.
- X
- XAdded Random's @owned command.
- X
- XPanics now dump the contents of the sigcontext struct in hex to the
- Xlogfile for debugging purposes.
- X
- X
- XChanges in version 1.5.3-FF.1 (Scott Goehring):
- X
- XWHO can take an argument; only names with the same prefix as the
- Xargument are displayed.
- X
- XLINK_OK code modified; ABODE flag added.
- X
- XPlayer may select format and order of WHO listing.
- X
- X!-bug fixed properly.
- X
- X------------------------------------------------------------------------
- X
- XChanges in version 1.5.3:
- X
- XGripes now get sent immediately to GOD when GOD_PRIV is defined. They
- Xcan be blocked by setting HAVEN.
- X
- XLimited @newpassword command to GOD when GOD_PRIV is defined. Otherwise
- Xany WIZARD could subvert GOD.
- X
- XAdded special case to do_name for changing the case of a player name.
- X
- XAdded interface changes, GOD_PRIV hacks, and HAVEN bit. [These Changes
- Xfrom Random at TinyHELL]
- X
- XGot rid of LOOKUP_COST; replaced it with special FIND_COST and PAGE_COST.
- Xfind defaults to being very expensive.
- X
- XAdded hash table for player name lookups. This change should
- Xeliminate a lot of thrashing.
- X
- XFixed ok_name test so that ! can appear after the beginning of a name.
- X
- X
- XChanges in version 1.5.2:
- X
- XAdded Stephen White's pronoun substitution code under #ifdef GENDER.
- X
- XChanged test for setting a created object's home to current room to
- Xrequire control of the room instead of linkability.
- X
- XObjects sent to rooms with @teleport go through dropto's.
- X
- XBoolean operators can no longer appear in names.
- X
- XAdded rudimentary string compression under #ifdef COMPRESS.
- X
- XFixed missing OUTPUTPREFIX and OUTPUTSUFFIX on WHO command in interface.
- X
- XFixed various small bugs not caught in 1.5.1.
- X
- X
- XChanges in version 1.5.1:
- X
- X@newpassword command added. Password checking added. 1p charge for
- Xchanging your own name eliminated to prevent confusion.
- X
- XDatabase structure modified to allow for boolean expressions as keys.
- XUSE_VFORK, DB_INITIAL_SIZE, and DB_DOUBLING #defines added to allow
- Xfor greater system-dependent configuration.
- X
- XWhisper command added.
- X
- XName formatting centralized. Names now include flags.
- X
- Xok_player_name() modified to reject names longer than
- XPLAYER_NAME_LIMIT.
- X
- XBoolean lock code added.
- X
- X
- XChanges in version 1.4.2:
- X
- XSmall bug fixes; okname() modified to reject names containing
- XARG_DELIMITER, democratized teleport added under #ifndef
- XRESTRICTED_TELEPORT.
- X
- X
- XChanges in version 1.4.1:
- X
- XRadically rewritten interface.c with fair command processing, command limits.
- X
- X------------------------------------------------------------------------
- END_OF_FILE
- if test 7507 -ne `wc -c <'CHANGES'`; then
- echo shar: \"'CHANGES'\" unpacked with wrong size!
- fi
- # end of 'CHANGES'
- fi
- if test -f 'compress.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'compress.c'\"
- else
- echo shar: Extracting \"'compress.c'\" \(2725 characters\)
- sed "s/^X//" >'compress.c' <<'END_OF_FILE'
- X/* Compression routines */
- X
- X/* These use a pathetically simple encoding that takes advantage of the */
- X/* eighth bit on a char; if you are using an international character set, */
- X/* they may need substantial patching. */
- X
- X#ifdef COMPRESS
- X
- X#define BUFFER_LEN 16384 /* nice big buffer */
- X
- X#define TOKEN_BIT 0x80 /* if on, it's a token */
- X#define TOKEN_MASK 0x7f /* for stripping out token value */
- X#define NUM_TOKENS (128)
- X#define MAX_CHAR (128)
- X
- X/* Top 128 bigrams in the CMU TinyMUD database as of 2/13/90 */
- Xstatic const char *tokens[NUM_TOKENS] = {
- X "e ", " t", "th", "he", "s ", " a", "ou", "in",
- X "t ", " s", "er", "d ", "re", "an", "n ", " i",
- X " o", "es", "st", "to", "or", "nd", "o ", "ar",
- X "r ", ", ", "on", " b", "ea", "it", "u ", " w",
- X "ng", "le", "is", "te", "en", "at", " c", "y ",
- X "ro", " f", "oo", "al", ". ", "a ", " d", "ut",
- X " h", "se", "nt", "ll", "g ", "yo", " l", " y",
- X " p", "ve", "f ", "as", "om", "of", "ha", "ed",
- X "h ", "hi", " r", "lo", "Yo", " m", "ne", "l ",
- X "li", "de", "el", "ta", "wa", "ri", "ee", "ti",
- X "no", "do", "Th", " e", "ck", "ur", "ow", "la",
- X "ac", "et", "me", "il", " g", "ra", "co", "ch",
- X "ma", "un", "so", "rt", "ai", "ce", "ic", "be",
- X " n", "k ", "ge", "ot", "si", "pe", "tr", "wi",
- X "e.", "ca", "rs", "ly", "ad", "we", "bo", "ho",
- X "ir", "fo", "ke", "us", "m ", " T", "di", ".." };
- X
- Xstatic char token_table[MAX_CHAR][MAX_CHAR];
- Xstatic int table_initialized = 0;
- X
- Xstatic void init_compress(void)
- X{
- X int i;
- X int j;
- X
- X for(i = 0; i < MAX_CHAR; i++) {
- X for(j = 0; j < MAX_CHAR; j++) {
- X token_table[i][j] = 0;
- X }
- X }
- X
- X for(i = 0; i < NUM_TOKENS; i++) {
- X token_table[tokens[i][0]][tokens[i][1]] = i | TOKEN_BIT;
- X }
- X
- X table_initialized = 1;
- X}
- X
- Xstatic int compressed(const char *s)
- X{
- X while(*s) {
- X if(*s++ & TOKEN_BIT) return 1;
- X }
- X return 0;
- X}
- X
- Xconst char *compress(const char *s)
- X{
- X static char buf[BUFFER_LEN];
- X char *to;
- X char token;
- X
- X if(!table_initialized) init_compress();
- X
- X if(compressed(s)) return s; /* already compressed */
- X
- X /* tokenize the first characters */
- X for(to = buf; s[0] && s[1]; to++) {
- X if(token = token_table[s[0]][s[1]]) {
- X *to = token;
- X s += 2;
- X } else {
- X *to = s[0];
- X s++;
- X }
- X }
- X
- X /* copy the last character (if any) and null */
- X while(*to++ = *s++);
- X
- X return buf;
- X}
- X
- Xconst char *uncompress(const char *s)
- X{
- X static char buf[BUFFER_LEN];
- X char *to;
- X const char *token;
- X
- X for(to = buf; *s; s++) {
- X if(*s & TOKEN_BIT) {
- X token = tokens[*s & TOKEN_MASK];
- X *to++ = *token++;
- X *to++ = *token;
- X } else {
- X *to++ = *s;
- X }
- X }
- X
- X *to++ = *s;
- X
- X return buf;
- X}
- X
- X#endif /* COMPRESS */
- X
- END_OF_FILE
- if test 2725 -ne `wc -c <'compress.c'`; then
- echo shar: \"'compress.c'\" unpacked with wrong size!
- fi
- # end of 'compress.c'
- fi
- if test -f 'create.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'create.c'\"
- else
- echo shar: Extracting \"'create.c'\" \(8647 characters\)
- sed "s/^X//" >'create.c' <<'END_OF_FILE'
- X#include "copyright.h"
- X
- X/* Commands that create new objects */
- X
- X#include "db.h"
- X#include "config.h"
- X#include "interface.h"
- X#include "externs.h"
- X
- X/* utility for open and link */
- Xstatic dbref parse_linkable_room(dbref player, object_flag_type thing,
- X const char *room_name)
- X{
- X dbref room;
- X
- X /* skip leading NUMBER_TOKEN if any */
- X if(*room_name == NUMBER_TOKEN) room_name++;
- X
- X /* parse room */
- X if(!string_compare(room_name, "here")) {
- X room = db[player].location;
- X } else if(!string_compare(room_name, "home")) {
- X return HOME; /* HOME is always linkable */
- X } else {
- X room = parse_dbref(room_name);
- X }
- X
- X /* check room */
- X if(room < 0 || room >= db_top
- X || Typeof(room) != TYPE_ROOM) {
- X notify(player, "That's not a room!");
- X return NOTHING;
- X } else if(!can_link_to(player, thing, room)) {
- X notify(player, "You can't link to that.");
- X return NOTHING;
- X } else {
- X return room;
- X }
- X}
- X
- X/* use this to create an exit */
- Xvoid do_open(dbref player, const char *direction, const char *linkto)
- X{
- X dbref loc;
- X dbref exit;
- X
- X#ifdef RESTRICTED_BUILDING
- X if(!Builder(player)) {
- X notify(player, "That command is restricted to authorized builders.");
- X return;
- X }
- X#endif /* RESTRICTED_BUILDING */
- X
- X if((loc = getloc(player)) == NOTHING) return;
- X if(!*direction) {
- X notify(player, "Open where?");
- X return;
- X } else if(!ok_name(direction)) {
- X notify(player, "That's a strange name for an exit!");
- X return;
- X }
- X
- X if(!controls(player, loc)) {
- X notify(player, "Permission denied.");
- X } else if(!payfor(player, EXIT_COST)) {
- X notify(player,
- X "Sorry, you don't have enough pennies to open an exit.");
- X } else {
- X /* create the exit */
- X exit = new_object();
- X
- X /* initialize everything */
- X db[exit].name = alloc_string(direction);
- X db[exit].owner = player;
- X db[exit].flags = TYPE_EXIT;
- X
- X /* link it in */
- X PUSH(exit, db[loc].exits);
- X
- X /* and we're done */
- X notify(player, "Opened.");
- X
- X /* check second arg to see if we should do a link */
- X if(*linkto != '\0') {
- X notify(player, "Trying to link...");
- X if((loc = parse_linkable_room(player, TYPE_EXIT, linkto)) !=
- X NOTHING) {
- X if(!payfor(player, LINK_COST)) {
- X notify(player, "You don't have enough pennies to link.");
- X } else {
- X /* it's ok, link it */
- X db[exit].location = loc;
- X notify(player, "Linked.");
- X }
- X }
- X }
- X }
- X}
- X
- X/* use this to link to a room that you own */
- X/* it seizes ownership of the exit */
- X/* costs 1 penny */
- X/* plus a penny transferred to the exit owner if they aren't you */
- X/* you must own the linked-to room AND specify it by room number */
- Xvoid do_link(dbref player, const char *name, const char *room_name)
- X{
- X dbref thing;
- X dbref room;
- X
- X init_match(player, name, TYPE_EXIT);
- X match_exit();
- X match_neighbor();
- X match_possession();
- X match_me();
- X match_here();
- X if(Wizard(player)) {
- X match_absolute();
- X match_player();
- X }
- X
- X if((thing = noisy_match_result()) != NOTHING) {
- X if((room = parse_linkable_room(player, Typeof(thing), room_name)) ==
- X NOTHING)
- X return;
- X switch(Typeof(thing)) {
- X case TYPE_EXIT:
- X /* we're ok, check the usual stuff */
- X if(db[thing].location != NOTHING) {
- X if(controls(player, thing)) {
- X
- X /*
- X * Changed 5/18/90 Fuzzy - exits linked to *home*
- X * break 'Typeof() call'
- X */
- X
- X if(db[thing].location >= 0 &&
- X Typeof(db[thing].location) == TYPE_PLAYER) {
- X notify(player, "That exit is being carried.");
- X } else {
- X notify(player, "That exit is already linked.");
- X }
- X } else {
- X notify(player, "Permission denied.");
- X }
- X } else {
- X /* handle costs */
- X if(db[thing].owner == player) {
- X if(!payfor(player, LINK_COST)) {
- X notify(player,
- X "It costs a penny to link this exit.");
- X return;
- X }
- X } else {
- X if(!payfor(player, LINK_COST + EXIT_COST)) {
- X notify(player,
- X "It costs two pennies to link this exit.");
- X return;
- X#ifdef RESTRICTED_BUILDING
- X } else if(!Builder(player)) {
- X notify(player,
- X "Only authorized builders may seize exits.");
- X#endif /* RESTRICTED_BUILDING */
- X } else {
- X /* pay the owner for his loss */
- X db[db[thing].owner].pennies += EXIT_COST;
- X }
- X }
- X
- X /* link has been validated and paid for; do it */
- X db[thing].owner = player;
- X db[thing].location = room;
- X
- X /* notify the player */
- X notify(player, "Linked.");
- X }
- X break;
- X case TYPE_PLAYER:
- X case TYPE_THING:
- X if(!controls(player, thing)) {
- X notify(player, "Permission denied.");
- X } else if(room == HOME) {
- X notify(player, "Can't set home to home.");
- X } else {
- X /* do the link */
- X db[thing].exits = room; /* home */
- X notify(player, "Home set.");
- X }
- X break;
- X case TYPE_ROOM:
- X if(!controls(player, thing)) {
- X notify(player, "Permission denied.");
- X } else {
- X /* do the link, in location */
- X db[thing].location = room; /* dropto */
- X notify(player, "Dropto set.");
- X }
- X break;
- X default:
- X notify(player, "Internal error: weird object type.");
- X writelog("PANIC weird object: Typeof(%d) = %d\n",
- X thing, Typeof(thing));
- X break;
- X }
- X }
- X}
- X
- X/* use this to create a room */
- Xvoid do_dig(dbref player, const char *name)
- X{
- X dbref room;
- X char buf[BUFFER_LEN];
- X
- X#ifdef RESTRICTED_BUILDING
- X if(!Builder(player)) {
- X notify(player, "That command is restricted to authorized builders.");
- X return;
- X }
- X#endif /* RESTRICTED_BUILDING */
- X
- X /* we don't need to know player's location! hooray! */
- X if(*name == '\0') {
- X notify(player, "Dig what?");
- X } else if(!ok_name(name)) {
- X notify(player, "That's a silly name for a room!");
- X } else if(!payfor(player, ROOM_COST)) {
- X notify(player, "Sorry, you don't have enough pennies to dig a room.");
- X } else {
- X room = new_object();
- X
- X /* Initialize everything */
- X db[room].name = alloc_string(name);
- X db[room].owner = player;
- X db[room].flags = TYPE_ROOM;
- X
- X sprintf(buf, "%s created with room number %d.", name, room);
- X notify(player, buf);
- X }
- X}
- X
- X/* use this to create an object */
- Xvoid do_create(dbref player, char *name, int cost)
- X{
- X dbref loc;
- X dbref thing;
- X
- X#ifdef RESTRICTED_BUILDING
- X if(!Builder(player)) {
- X notify(player, "That command is restricted to authorized builders.");
- X return;
- X }
- X#endif /* RESTRICTED_BUILDING */
- X
- X if(*name == '\0') {
- X notify(player, "Create what?");
- X return;
- X } else if(!ok_name(name)) {
- X notify(player, "That's a silly name for a thing!");
- X return;
- X } else if(cost < 0) {
- X notify(player, "You can't create an object for less than nothing!");
- X return;
- X } else if(cost < OBJECT_COST) {
- X cost = OBJECT_COST;
- X }
- X
- X if(!payfor(player, cost)) {
- X notify(player, "Sorry, you don't have enough pennies.");
- X } else {
- X /* create the object */
- X thing = new_object();
- X
- X /* initialize everything */
- X db[thing].name = alloc_string(name);
- X db[thing].location = player;
- X db[thing].owner = player;
- X db[thing].pennies = OBJECT_ENDOWMENT(cost);
- X db[thing].flags = TYPE_THING;
- X
- X /* endow the object */
- X if(db[thing].pennies > MAX_OBJECT_ENDOWMENT) {
- X db[thing].pennies = MAX_OBJECT_ENDOWMENT;
- X }
- X
- X /* home is here (if we can link to it) or player's home */
- X if((loc = db[player].location) != NOTHING
- X && controls(player, loc)) {
- X db[thing].exits = loc; /* home */
- X } else {
- X db[thing].exits = db[player].exits; /* home */
- X }
- X
- X /* link it in */
- X PUSH(thing, db[player].contents);
- X
- X /* and we're done */
- X notify(player, "Created.");
- X }
- X}
- X
- X#ifdef REGISTRATION
- Xvoid do_pcreate (dbref player, char *newplayer, char *newpass)
- X{
- X dbref ptmp;
- X
- X#ifdef GOD_MODE && GOD_ONLY_PCREATE
- X if (!God(player))
- X#ifndef TINKER
- X notify (player, "Only GOD can create a new player.");
- X#else TINKER
- X notify (player, "Only the Master Tinker can create a new player.");
- X#endif TINKER
- X#else GOD_MODE && GOD_ONLY_PCREATE
- X if (!Wizard(player))
- X#ifndef TINKER
- X notify (player, "Only a Wizard can create a new player.");
- X#else TINKER
- X notify (player, "Only a Tinker can create a new player.");
- X#endif TINKER
- X#endif GOD_MODE && GOD_ONLY_PCREATE
- X else if (!*newplayer || !*newpass)
- X notify (player, "You must specify name and password.");
- X else {
- X ptmp = create_player (newplayer, newpass);
- X if (ptmp == NOTHING) {
- X notify(player, "Either there is already a player with that name, or that name is illegal.");
- X writelog("FAILED CREATE %s by %s\n",newplayer,db[player].name);
- X } else {
- X char buf[512];
- X sprintf(buf, "%s created as object #%d.",db[ptmp].name,ptmp);
- X notify(player, buf);
- X writelog("CREATED %s(%d) by %s\n",db[ptmp].name,ptmp,
- X db[player].name);
- X }
- X }
- X}
- X#endif REGISTRATION
- END_OF_FILE
- if test 8647 -ne `wc -c <'create.c'`; then
- echo shar: \"'create.c'\" unpacked with wrong size!
- fi
- # end of 'create.c'
- fi
- if test -f 'db.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'db.h'\"
- else
- echo shar: Extracting \"'db.h'\" \(5703 characters\)
- sed "s/^X//" >'db.h' <<'END_OF_FILE'
- X#include "copyright.h"
- X
- X#ifndef __DB_H
- X#define __DB_H
- X#include <stdio.h>
- X
- Xextern void *malloc(unsigned long);
- Xextern void *realloc(void *, unsigned long);
- Xextern void free(void *);
- X
- X#ifdef TEST_MALLOC
- Xextern int malloc_count;
- X#define malloc(x) (malloc_count++, malloc(x))
- X#define free(x) (malloc_count--, free(x))
- X#endif /* TEST_MALLOC */
- X
- Xtypedef int dbref; /* offset into db */
- X
- X#define TYPE_ROOM 0x0
- X#define TYPE_THING 0x1
- X#define TYPE_EXIT 0x2
- X#define TYPE_PLAYER 0x3
- X#define NOTYPE 0x7 /* no particular type */
- X#define TYPE_MASK 0x7 /* room for expansion */
- X#define ANTILOCK 0x8 /* negates key (*OBSOLETE*) */
- X#define WIZARD 0x10 /* gets automatic control */
- X#define LINK_OK 0x20 /* anybody can link exits to this room */
- X#define DARK 0x40 /* contents of room are not printed */
- X#define TEMPLE 0x80 /* objects dropped in this room go home */
- X#define STICKY 0x100 /* this object goes home when dropped */
- X
- X#ifdef RESTRICTED_BUILDING
- X#define BUILDER 0x200 /* this player can use construction commands */
- X#endif /* RESTRICTED_BUILDING */
- X
- X#define HAVEN 0x400 /* this room prohibits killing */
- X#define ABODE 0x800 /* can link objects or players here */
- X
- X#ifdef GENDER
- X#define GENDER_MASK 0x3000 /* 2 bits of gender */
- X#define GENDER_SHIFT 12 /* 0x1000 is 12 bits over (for shifting) */
- X#define GENDER_UNASSIGNED 0x0 /* unassigned - the default */
- X#define GENDER_NEUTER 0x1 /* neuter */
- X#define GENDER_FEMALE 0x2 /* for women */
- X#define GENDER_MALE 0x3 /* for men */
- X
- X#ifdef ROBOT_MODE
- X#define ROBOT 0x4000 /* Can set OUTPUTPREFIX */
- X#endif ROBOT_MODE
- X
- X#define UNWANTED 0x8000 /* can be chowned */
- X
- X#define TABULAR_WHO 0x10000
- X#define REVERSED_WHO 0x20000
- X
- X#define Genderof(x) ((db[(x)].flags & GENDER_MASK) >> GENDER_SHIFT)
- X#endif /* GENDER */
- X
- Xtypedef int object_flag_type;
- X
- X#define Flag(x,f) ((db[(x)].flags & (f)) != 0)
- X
- X#define Typeof(x) (db[(x)].flags & TYPE_MASK)
- X#define Wizard(x) ((db[(x)].flags & WIZARD) != 0)
- X#ifdef ROBOT_MODE
- X#define Robot(x) ((db[(x)].flags & ROBOT) != 0)
- X#endif ROBOT_MODE
- X#define Dark(x) ((db[(x)].flags & DARK) != 0)
- X#ifdef GOD_PRIV
- X#define GOD ((dbref)1)
- X#define God(x) ((x)==GOD)
- X#endif GOD_PRIV
- X
- X#ifdef RECYCLE
- X#define RECYCLER "Recycler"
- X#endif
- X
- X#ifdef RESTRICTED_BUILDING
- X#define Builder(x) ((db[(x)].flags & (WIZARD|BUILDER)) != 0)
- X#endif /* RESTRICTED_BUILDING */
- X
- X/* Boolean expressions, for locks */
- Xtypedef char boolexp_type;
- X
- X#define BOOLEXP_AND 0
- X#define BOOLEXP_OR 1
- X#define BOOLEXP_NOT 2
- X#define BOOLEXP_CONST 3
- X
- Xstruct boolexp {
- X boolexp_type type;
- X struct boolexp *sub1;
- X struct boolexp *sub2;
- X dbref thing;
- X};
- X
- X#define TRUE_BOOLEXP ((struct boolexp *) 0)
- X
- X/* special dbref's */
- X#define NOTHING (-1) /* null dbref */
- X#define AMBIGUOUS (-2) /* multiple possibilities, for matchers */
- X#define HOME (-3) /* virtual room, represents mover's home */
- X
- Xstruct object {
- X const char *name;
- X const char *description;
- X dbref location; /* pointer to container */
- X /* for exits, pointer to destination */
- X dbref contents; /* pointer to first item */
- X dbref exits; /* pointer to first exit for rooms */
- X /* pointer to home for things and players */
- X dbref next; /* pointer to next in contents/exits chain */
- X
- X /* the following are used for pickups for things, entry for exits */
- X struct boolexp *key; /* if not NOTHING, must have this to do op */
- X const char *fail_message; /* what you see if op fails */
- X const char *succ_message; /* what you see if op succeeds */
- X /* other messages get your name prepended, so if your name is "Foo", */
- X /* and osuccess = "disappears in a blast of gamma radiation." */
- X /* then others see "Foo disappears in a blast of gamma radiation." */
- X /* (At some point I may put in Maven-style %-substitutions.) */
- X const char *ofail; /* what others see if op fails */
- X const char *osuccess; /* what others see if op succeeds */
- X
- X dbref owner; /* who controls this object */
- X int pennies; /* number of pennies object contains */
- X object_flag_type flags;
- X const char *password; /* password for players */
- X};
- X
- Xextern struct object *db;
- Xextern dbref db_top;
- X
- Xextern const char *alloc_string(const char *s);
- X
- Xextern dbref new_object(); /* return a new object */
- X
- Xextern dbref getref (FILE *); /* Read a database reference from a file. */
- X
- Xextern void putref (FILE *, dbref); /* Write one ref to the file */
- X
- Xextern struct boolexp *getboolexp(FILE *); /* get a boolexp */
- Xextern void putboolexp(FILE *, struct boolexp *); /* put a boolexp */
- X
- Xextern int db_write_object(FILE *, dbref); /* write one object to file */
- X
- Xextern dbref db_write(FILE *f); /* write db to file, return # of objects */
- X
- Xextern dbref db_read(FILE *f); /* read db from file, return # of objects */
- X /* Warning: destroys existing db contents! */
- X
- Xextern void free_boolexp(struct boolexp *);
- Xextern void db_free(void);
- X
- Xextern dbref parse_dbref(const char *); /* parse a dbref */
- X
- X#define DOLIST(var, first) \
- X for((var) = (first); (var) != NOTHING; (var) = db[(var)].next)
- X#define PUSH(thing, locative) \
- X ((db[(thing)].next = (locative)), (locative) = (thing))
- X#define getloc(thing) (db[thing].location)
- X
- X/*
- X Usage guidelines:
- X
- X To refer to objects use db[object_ref]. Pointers to objects may
- X become invalid after a call to new_object().
- X
- X The programmer is responsible for managing storage for string
- X components of entries; db_read will produce malloc'd strings. The
- X alloc_string routine is provided for generating malloc'd strings
- X duplicates of other strings. Note that db_free and db_read will
- X attempt to free any non-NULL string that exists in db when they are
- X invoked.
- X*/
- X#endif /* __DB_H */
- END_OF_FILE
- if test 5703 -ne `wc -c <'db.h'`; then
- echo shar: \"'db.h'\" unpacked with wrong size!
- fi
- # end of 'db.h'
- fi
- if test -f 'match.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'match.c'\"
- else
- echo shar: Extracting \"'match.c'\" \(5261 characters\)
- sed "s/^X//" >'match.c' <<'END_OF_FILE'
- X#include "copyright.h"
- X
- X/* Routines for parsing arguments */
- X#include <ctype.h>
- X
- X#include "db.h"
- X#include "config.h"
- X#include "match.h"
- X
- X#define DOWNCASE(x) (isupper(x) ? tolower(x) : (x))
- X
- Xstatic dbref exact_match = NOTHING; /* holds result of exact match */
- Xstatic int check_keys = 0; /* if non-zero, check for keys */
- Xstatic dbref last_match = NOTHING; /* holds result of last match */
- Xstatic int match_count; /* holds total number of inexact matches */
- Xstatic dbref match_who; /* player who is being matched around */
- Xstatic const char *match_name; /* name to match */
- Xstatic int preferred_type = NOTYPE; /* preferred type */
- X
- Xvoid init_match(dbref player, const char *name, int type)
- X{
- X exact_match = last_match = NOTHING;
- X match_count = 0;
- X match_who = player;
- X match_name = name;
- X check_keys = 0;
- X preferred_type = type;
- X}
- X
- Xvoid init_match_check_keys(dbref player, const char *name, int type)
- X{
- X init_match(player, name, type);
- X check_keys = 1;
- X}
- X
- Xstatic dbref choose_thing(dbref thing1, dbref thing2)
- X{
- X int has1;
- X int has2;
- X
- X if(thing1 == NOTHING) {
- X return thing2;
- X } else if(thing2 == NOTHING) {
- X return thing1;
- X }
- X
- X if(preferred_type != NOTYPE) {
- X if(Typeof(thing1) == preferred_type) {
- X if(Typeof(thing2) != preferred_type) {
- X return thing1;
- X }
- X } else if(Typeof(thing2) == preferred_type) {
- X return thing2;
- X }
- X }
- X
- X if(check_keys) {
- X has1 = could_doit(match_who, thing1);
- X has2 = could_doit(match_who, thing2);
- X
- X if(has1 && !has2) {
- X return thing1;
- X } else if (has2 && !has1) {
- X return thing2;
- X }
- X /* else fall through */
- X }
- X
- X return (random() % 2 ? thing1 : thing2);
- X}
- X
- Xvoid match_player(void)
- X{
- X dbref match;
- X const char *p;
- X
- X if(*match_name == LOOKUP_TOKEN) {
- X for(p = match_name + 1; isspace(*p); p++);
- X if((match = lookup_player(p)) != NOTHING) {
- X exact_match = match;
- X }
- X }
- X}
- X
- X/* returns nnn if name = #nnn, else NOTHING */
- Xstatic dbref absolute_name(void)
- X{
- X dbref match;
- X
- X if(*match_name == NUMBER_TOKEN) {
- X match = parse_dbref(match_name+1);
- X if(match < 0 || match >= db_top) {
- X return NOTHING;
- X } else {
- X return match;
- X }
- X } else {
- X return NOTHING;
- X }
- X}
- X
- Xvoid match_absolute(void)
- X{
- X dbref match;
- X
- X if((match = absolute_name()) != NOTHING) {
- X exact_match = match;
- X }
- X}
- X
- Xvoid match_me(void)
- X{
- X if(!string_compare(match_name, "me")) {
- X exact_match = match_who;
- X }
- X}
- X
- Xvoid match_here(void)
- X{
- X if(!string_compare(match_name, "here")
- X && db[match_who].location != NOTHING) {
- X exact_match = db[match_who].location;
- X }
- X}
- X
- Xstatic void match_list(dbref first)
- X{
- X dbref absolute;
- X
- X absolute = absolute_name();
- X if(!controls(match_who, absolute)) absolute = NOTHING;
- X
- X DOLIST(first, first) {
- X if(first == absolute) {
- X exact_match = first;
- X return;
- X } else if(!string_compare(db[first].name, match_name)) {
- X /* if there are multiple exact matches, randomly choose one */
- X exact_match = choose_thing(exact_match, first);
- X } else if(string_match(db[first].name, match_name)) {
- X last_match = first;
- X match_count++;
- X }
- X }
- X}
- X
- Xvoid match_possession(void)
- X{
- X match_list(db[match_who].contents);
- X}
- X
- Xvoid match_neighbor(void)
- X{
- X dbref loc;
- X
- X if((loc = db[match_who].location) != NOTHING) {
- X match_list(db[loc].contents);
- X }
- X}
- X
- Xvoid match_exit(void)
- X{
- X dbref loc;
- X dbref exit;
- X dbref absolute;
- X const char *match;
- X const char *p;
- X
- X if((loc = db[match_who].location) != NOTHING) {
- X absolute = absolute_name();
- X if(!controls(match_who, absolute)) absolute = NOTHING;
- X
- X DOLIST(exit, db[loc].exits) {
- X if(exit == absolute) {
- X exact_match = exit;
- X } else {
- X match = db[exit].name;
- X while(*match) {
- X /* check out this one */
- X for(p = match_name;
- X (*p
- X && DOWNCASE(*p) == DOWNCASE(*match)
- X && *match != EXIT_DELIMITER);
- X p++, match++);
- X /* did we get it? */
- X if(*p == '\0') {
- X /* make sure there's nothing afterwards */
- X while(isspace(*match)) match++;
- X if(*match == '\0' || *match == EXIT_DELIMITER) {
- X /* we got it */
- X exact_match = choose_thing(exact_match, exit);
- X goto next_exit; /* got this match */
- X }
- X }
- X /* we didn't get it, find next match */
- X while(*match && *match++ != EXIT_DELIMITER);
- X while(isspace(*match)) match++;
- X }
- X }
- X next_exit:
- X ;
- X }
- X }
- X}
- X
- Xvoid match_everything(void)
- X{
- X match_exit();
- X match_neighbor();
- X match_possession();
- X match_me();
- X match_here();
- X if(Wizard(match_who)) {
- X match_absolute();
- X match_player();
- X }
- X}
- X
- Xdbref match_result(void)
- X{
- X if(exact_match != NOTHING) {
- X return exact_match;
- X } else {
- X switch(match_count) {
- X case 0:
- X return NOTHING;
- X case 1:
- X return last_match;
- X default:
- X return AMBIGUOUS;
- X }
- X }
- X}
- X
- X/* use this if you don't care about ambiguity */
- Xdbref last_match_result(void)
- X{
- X if(exact_match != NOTHING) {
- X return exact_match;
- X } else {
- X return last_match;
- X }
- X}
- X
- Xdbref noisy_match_result(void)
- X{
- X dbref match;
- X
- X switch(match = match_result()) {
- X case NOTHING:
- X notify(match_who, NOMATCH_MESSAGE);
- X return NOTHING;
- X case AMBIGUOUS:
- X notify(match_who, AMBIGUOUS_MESSAGE);
- X return NOTHING;
- X default:
- X return match;
- X }
- X}
- X
- END_OF_FILE
- if test 5261 -ne `wc -c <'match.c'`; then
- echo shar: \"'match.c'\" unpacked with wrong size!
- fi
- # end of 'match.c'
- fi
- if test -f 'move.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'move.c'\"
- else
- echo shar: Extracting \"'move.c'\" \(8534 characters\)
- sed "s/^X//" >'move.c' <<'END_OF_FILE'
- X#include "copyright.h"
- X
- X#include "db.h"
- X#include "config.h"
- X#include "interface.h"
- X#include "match.h"
- X#include "externs.h"
- X
- Xvoid moveto(dbref what, dbref where)
- X{
- X dbref loc;
- X
- X /* remove what from old loc */
- X if((loc = db[what].location) != NOTHING) {
- X db[loc].contents = remove_first(db[loc].contents, what);
- X }
- X
- X /* test for special cases */
- X switch(where) {
- X case NOTHING:
- X db[what].location = NOTHING;
- X return; /* NOTHING doesn't have contents */
- X case HOME:
- X where = db[what].exits; /* home */
- X break;
- X }
- X
- X /* now put what in where */
- X PUSH(what, db[where].contents);
- X
- X db[what].location = where;
- X}
- X
- Xstatic void send_contents(dbref loc, dbref dest)
- X{
- X dbref first;
- X dbref rest;
- X
- X first = db[loc].contents;
- X db[loc].contents = NOTHING;
- X
- X /* blast locations of everything in list */
- X DOLIST(rest, first) {
- X db[rest].location = NOTHING;
- X }
- X
- X while(first != NOTHING) {
- X rest = db[first].next;
- X if(Typeof(first) != TYPE_THING) {
- X moveto(first, loc);
- X } else {
- X moveto(first, (db[first].flags & STICKY) ? HOME : dest);
- X }
- X first = rest;
- X }
- X
- X db[loc].contents = reverse(db[loc].contents);
- X}
- X
- Xvoid maybe_dropto(dbref loc, dbref dropto)
- X{
- X dbref thing;
- X
- X if(loc == dropto) return; /* bizarre special case */
- X
- X /* check for players */
- X DOLIST(thing, db[loc].contents) {
- X if(Typeof(thing) == TYPE_PLAYER) return;
- X }
- X
- X /* no players, send everything to the dropto */
- X send_contents(loc, dropto);
- X}
- X
- Xvoid enter_room(dbref player, dbref loc)
- X{
- X dbref old;
- X dbref dropto;
- X char buf[BUFFER_LEN];
- X
- X /* check for room == HOME */
- X if(loc == HOME) loc = db[player].exits; /* home */
- X
- X /* get old location */
- X old = db[player].location;
- X
- X /* check for self-loop */
- X /* self-loops don't do move or other player notification */
- X /* but you still get autolook and penny check */
- X if(loc != old) {
- X
- X if(old != NOTHING) {
- X /* notify others unless DARK */
- X if(!Dark(old) && !Dark(player)) {
- X sprintf(buf, "%s has left.", db[player].name);
- X notify_except(db[old].contents, player, buf);
- X }
- X }
- X
- X /* go there */
- X moveto(player, loc);
- X
- X /* if old location has STICKY dropto, send stuff through it */
- X if(old != NOTHING
- X && (dropto = db[old].location) != NOTHING
- X && (db[old].flags & STICKY)) {
- X maybe_dropto(old, dropto);
- X }
- X
- X /* tell other folks in new location if not DARK */
- X if(!Dark(loc) && !Dark(player)) {
- X sprintf(buf, "%s has arrived.", db[player].name);
- X notify_except(db[loc].contents, player, buf);
- X }
- X }
- X
- X /* autolook */
- X look_room(player, loc);
- X
- X /* check for pennies */
- X if(!controls(player, loc)
- X && db[player].pennies <= MAX_PENNIES
- X && random() % PENNY_RATE == 0) {
- X notify(player, "You found a penny!");
- X db[player].pennies++;
- X }
- X}
- X
- Xvoid send_home(dbref thing)
- X{
- X switch(Typeof(thing)) {
- X case TYPE_PLAYER:
- X /* send his possessions home first! */
- X /* that way he sees them when he arrives */
- X send_contents(thing, HOME);
- X enter_room(thing, db[thing].exits); /* home */
- X break;
- X case TYPE_THING:
- X moveto(thing, db[thing].exits); /* home */
- X break;
- X default:
- X /* no effect */
- X break;
- X }
- X}
- X
- Xint can_move(dbref player, const char *direction)
- X{
- X if(!string_compare(direction, "home")) return 1;
- X
- X /* otherwise match on exits */
- X init_match(player, direction, TYPE_EXIT);
- X match_exit();
- X return(last_match_result() != NOTHING);
- X}
- X
- Xvoid do_move(dbref player, const char *direction)
- X{
- X dbref exit;
- X dbref loc;
- X char buf[BUFFER_LEN];
- X
- X if(!string_compare(direction, "home")) {
- X /* send him home */
- X /* but steal all his possessions */
- X if((loc = db[player].location) != NOTHING) {
- X /* tell everybody else */
- X sprintf(buf, "%s goes home.", db[player].name);
- X notify_except(db[loc].contents, player, buf);
- X }
- X /* give the player the messages */
- X notify(player, "There's no place like home...");
- X notify(player, "There's no place like home...");
- X notify(player, "There's no place like home...");
- X notify(player, "You wake up back home, without your possessions.");
- X send_home(player);
- X } else {
- X /* find the exit */
- X init_match_check_keys(player, direction, TYPE_EXIT);
- X match_exit();
- X switch(exit = match_result()) {
- X case NOTHING:
- X notify(player, "You can't go that way.");
- X break;
- X case AMBIGUOUS:
- X notify(player, "I don't know which way you mean!");
- X break;
- X default:
- X /* we got one */
- X /* check to see if we got through */
- X if(can_doit(player, exit, "You can't go that way.")) {
- X enter_room(player, db[exit].location);
- X }
- X break;
- X }
- X }
- X}
- X
- Xvoid do_get(dbref player, const char *what)
- X{
- X dbref loc;
- X dbref thing;
- X
- X init_match_check_keys(player, what, TYPE_THING);
- X match_neighbor();
- X match_exit();
- X if(Wizard(player)) match_absolute(); /* the wizard has long fingers */
- X
- X if((thing = noisy_match_result()) != NOTHING) {
- X if(db[thing].location == player) {
- X notify(player, "You already have that!");
- X return;
- X }
- X switch(Typeof(thing)) {
- X case TYPE_THING:
- X if(can_doit(player, thing, "You can't pick that up.")) {
- X moveto(thing, player);
- X notify(player, "Taken.");
- X }
- X break;
- X case TYPE_EXIT:
- X if(!controls(player, thing)) {
- X notify(player, "You can't pick that up.");
- X } else if(db[thing].location != NOTHING) {
- X notify(player, "You can't pick up a linked exit.");
- X#ifdef RESTRICTED_BUILDING
- X } else if(!Builder(player)) {
- X notify(player, "Only authorized builders may pick up exits.");
- X#endif /* RESTRICTED_BUILDING */
- X } else {
- X /* take it out of location */
- X if((loc = getloc(player)) == NOTHING) return;
- X if(!member(thing, db[loc].exits)) {
- X notify(player,
- X "You can't pick up an exit from another room.");
- X return;
- X }
- X db[loc].exits = remove_first(db[loc].exits, thing);
- X PUSH(thing, db[player].contents);
- X db[thing].location = player;
- X notify(player, "Exit taken.");
- X }
- X break;
- X default:
- X notify(player, "You can't take that!");
- X break;
- X }
- X }
- X}
- X
- Xvoid do_drop(dbref player, const char *name)
- X{
- X dbref loc;
- X dbref thing;
- X char buf[BUFFER_LEN];
- X int reward;
- X
- X if((loc = getloc(player)) == NOTHING) return;
- X
- X init_match(player, name, TYPE_THING);
- X match_possession();
- X
- X switch(thing = match_result()) {
- X case NOTHING:
- X notify(player, "You don't have that!");
- X break;
- X case AMBIGUOUS:
- X notify(player, "I don't know which you mean!");
- X break;
- X default:
- X if(db[thing].location != player &&
- X !(Typeof(thing) == TYPE_EXIT) && db[thing].location == NOTHING) {
- X /* Should not ever happen. */
- X notify(player, "You can't drop that.");
- X } else if(Typeof(thing) == TYPE_EXIT) {
- X /* special behavior for exits */
- X if(!controls(player, loc)) {
- X notify(player, "You can't put an exit down here.");
- X return;
- X }
- X /* else we can put it down */
- X moveto(thing, NOTHING); /* take it out of the pack */
- X PUSH(thing, db[loc].exits);
- X notify(player, "Exit dropped.");
- X } else if(db[loc].flags & TEMPLE) {
- X /* sacrifice time */
- X send_home(thing);
- X sprintf(buf,
- X "%s is consumed in a burst of flame!", db[thing].name);
- X notify(player, buf);
- X#ifndef TINKER
- X sprintf(buf, "%s sacrifices %s.", db[player].name, db[thing].name);
- X#else TINKER
- X sprintf(buf, "%s donates %s.", db[player].name, db[thing].name);
- X#endif TINKER
- X notify_except(db[loc].contents, player, buf);
- X
- X /* check for reward */
- X if(!controls(player, thing)) {
- X reward = db[thing].pennies;
- X if(reward < 1 || db[player].pennies > MAX_PENNIES) {
- X reward = 1;
- X } else if(reward > MAX_OBJECT_ENDOWMENT) {
- X reward = MAX_OBJECT_ENDOWMENT;
- X }
- X
- X db[player].pennies += reward;
- X sprintf(buf,
- X "You have received %d %s for your donation.",
- X reward,
- X reward == 1 ? "penny" : "pennies");
- X notify(player, buf);
- X }
- X } else if(db[thing].flags & STICKY) {
- X send_home(thing);
- X notify(player, "Dropped.");
- X } else if(db[loc].location != NOTHING && !(db[loc].flags & STICKY)) {
- X /* location has immediate dropto */
- X moveto(thing, db[loc].location);
- X notify(player, "Dropped.");
- X } else if((db[thing].flags & DARK) && !can_link_to(player,Typeof(thing),loc)) {
- X notify(player, "You cannot drop that DARK object here.");
- X } else {
- X moveto(thing, loc);
- X notify(player, "Dropped.");
- X sprintf(buf, "%s dropped %s.", db[player].name, db[thing].name);
- X notify_except(db[loc].contents, player, buf);
- X }
- X break;
- X }
- X}
- END_OF_FILE
- if test 8534 -ne `wc -c <'move.c'`; then
- echo shar: \"'move.c'\" unpacked with wrong size!
- fi
- # end of 'move.c'
- fi
- if test -f 'predicates.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'predicates.c'\"
- else
- echo shar: Extracting \"'predicates.c'\" \(6557 characters\)
- sed "s/^X//" >'predicates.c' <<'END_OF_FILE'
- X#include "copyright.h"
- X
- X/* Predicates for testing various conditions */
- X
- X#include <ctype.h>
- X
- X#include "db.h"
- X#include "interface.h"
- X#include "config.h"
- X#include "externs.h"
- X
- Xvoid pronoun_substitute(char *result, dbref player, const char *str);
- X
- Xint can_link_to(dbref who, object_flag_type what, dbref where)
- X{
- X return(where >= 0 &&
- X where < db_top &&
- X Typeof(where) == TYPE_ROOM &&
- X (controls(who, where) ||
- X (what == NOTYPE &&
- X (Flag(where,LINK_OK|ABODE))) ||
- X (what == TYPE_ROOM &&
- X (Flag(where,ABODE))) ||
- X (what == TYPE_EXIT &&
- X (Flag(where,LINK_OK))) ||
- X ((what == TYPE_PLAYER || what == TYPE_THING) &&
- X#ifdef ROBOT_MODE
- X (what != TYPE_PLAYER || !Robot(who) || !Robot(where)) &&
- X#endif ROBOT_MODE
- X Flag(where,ABODE))));
- X }
- X
- X/*
- X * Check whether a player can perform an action...robotic players are
- X * now implicitly barred from performing actions on things with the
- X * robot flag set. 5/18/90 - Fuzzy
- X */
- X
- Xint could_doit(dbref player, dbref thing)
- X{
- X if(Typeof(thing) != TYPE_ROOM && db[thing].location == NOTHING) return 0;
- X
- X#ifdef ROBOT_MODE
- X if(Typeof(thing) != TYPE_PLAYER && Robot(player) && Robot(thing)) return 0;
- X if(Typeof(thing) == TYPE_EXIT && Robot(player) &&
- X db[thing].location >= 0 && Robot(db[thing].location)) return 0;
- X#endif ROBOT_MODE
- X
- X return(eval_boolexp (player, db[thing].key));
- X}
- X
- Xint can_doit(dbref player, dbref thing, const char *default_fail_msg)
- X{
- X dbref loc;
- X char buf[BUFFER_LEN];
- X
- X if((loc = getloc(player)) == NOTHING) return 0;
- X
- X if(!could_doit(player, thing)) {
- X /* can't do it */
- X if(db[thing].fail_message) {
- X notify(player, db[thing].fail_message);
- X } else if(default_fail_msg) {
- X notify(player, default_fail_msg);
- X }
- X
- X if(db[thing].ofail && !Dark(player)) {
- X#ifdef GENDER
- X pronoun_substitute(buf, player, db[thing].ofail);
- X#else
- X sprintf(buf, "%s %s", db[player].name, db[thing].ofail);
- X#endif /* GENDER */
- X notify_except(db[loc].contents, player, buf);
- X }
- X
- X return 0;
- X } else {
- X /* can do it */
- X if(db[thing].succ_message) {
- X notify(player, db[thing].succ_message);
- X }
- X
- X if(db[thing].osuccess && !Dark(player)) {
- X#ifdef GENDER
- X pronoun_substitute(buf, player, db[thing].osuccess);
- X#else
- X sprintf(buf, "%s %s", db[player].name, db[thing].osuccess);
- X#endif /* GENDER */
- X notify_except(db[loc].contents, player, buf);
- X }
- X
- X return 1;
- X }
- X}
- X
- Xint can_see(dbref player, dbref thing, int can_see_loc)
- X{
- X if(player == thing || Typeof(thing) == TYPE_EXIT) {
- X return 0;
- X } else if(can_see_loc) {
- X return(!Dark(thing) || controls(player, thing));
- X } else {
- X /* can't see loc */
- X return(controls(player, thing));
- X }
- X}
- X
- Xint controls(dbref who, dbref what)
- X{
- X /* Wizard controls everything */
- X /* owners control their stuff */
- X return(what >= 0
- X && what < db_top
- X && (Wizard(who)
- X || who == db[what].owner));
- X}
- X
- Xint can_link(dbref who, dbref what)
- X{
- X return((Typeof(what) == TYPE_EXIT && db[what].location == NOTHING)
- X || controls(who, what));
- X}
- X
- Xint payfor(dbref who, int cost)
- X{
- X if(Wizard(who)) {
- X return 1;
- X } else if(db[who].pennies >= cost) {
- X db[who].pennies -= cost;
- X return 1;
- X } else {
- X return 0;
- X }
- X}
- X
- Xint word_start (const char *str, const char let)
- X{
- X int chk;
- X
- X for (chk = 1; *str; str++) {
- X if (chk && *str == let) return 1;
- X chk = *str == ' ';
- X }
- X return 0;
- X}
- X
- X
- Xint ok_name(const char *name)
- X{
- X return (name
- X && *name
- X && *name != LOOKUP_TOKEN
- X && *name != NUMBER_TOKEN
- X && !index(name, ARG_DELIMITER)
- X && !index(name, AND_TOKEN)
- X && !index(name, OR_TOKEN)
- X && !word_start(name, NOT_TOKEN)
- X#ifdef NOFAKES
- X && string_compare(name, "A")
- X && string_compare(name, "An")
- X && string_compare(name, "The")
- X && string_compare(name, "You")
- X && string_compare(name, "Your")
- X && string_compare(name, "Going")
- X && string_compare(name, "Huh?")
- X#endif NOFAKES
- X && string_compare(name, "me")
- X && string_compare(name, "home")
- X && string_compare(name, "here"));
- X}
- X
- Xint ok_player_name(const char *name)
- X{
- X const char *scan;
- X
- X if(!ok_name(name) || strlen(name) > PLAYER_NAME_LIMIT) return 0;
- X
- X for(scan = name; *scan; scan++) {
- X if(!(isprint(*scan) && !isspace(*scan))) { /* was isgraph(*scan) */
- X return 0;
- X }
- X }
- X
- X /* lookup name to avoid conflicts */
- X return (lookup_player(name) == NOTHING);
- X}
- X
- Xint ok_password(const char *password)
- X{
- X const char *scan;
- X
- X if(*password == '\0') return 0;
- X
- X for(scan = password; *scan; scan++) {
- X if(!(isprint(*scan) && !isspace(*scan))) {
- X return 0;
- X }
- X }
- X
- X return 1;
- X}
- X
- X#ifdef GENDER
- X/*
- X * pronoun_substitute()
- X *
- X * %-type substitutions for pronouns
- X *
- X * %s/%S for subjective pronouns (he/she/it, He/She/It)
- X * %o/%O for objective pronouns (him/her/it, Him/Her/It)
- X * %p/%P for possessive pronouns (his/her/its, His/Her/Its)
- X * %n for the player's name.
- X */
- Xvoid pronoun_substitute(char *result, dbref player, const char *str)
- X{
- X char c;
- X
- X const static char *subjective[4] = { "", "it", "she", "he" };
- X const static char *possessive[4] = { "", "its", "her", "his" };
- X const static char *objective[4] = { "", "it", "her", "him" };
- X
- X#ifdef COMPRESS
- X str = uncompress(str);
- X#endif /* COMPRESS */
- X strcpy(result, db[player].name);
- X result += strlen(result);
- X *result++ = ' ';
- X while (*str) {
- X if(*str == '%') {
- X *result = '\0';
- X c = *(++str);
- X if (Genderof(player) == GENDER_UNASSIGNED) {
- X switch(c) {
- X case 'n':
- X case 'N':
- X case 'o':
- X case 'O':
- X case 's':
- X case 'S':
- X strcat(result, db[player].name);
- X break;
- X case 'p':
- X case 'P':
- X strcat(result, db[player].name);
- X strcat(result, "'s");
- X break;
- X default:
- X result[0] = *str;
- X result[1] = 0;
- X break;
- X }
- X str++;
- X result += strlen(result);
- X } else {
- X switch (c) {
- X case 's':
- X case 'S':
- X strcat(result, subjective[Genderof(player)]);
- X break;
- X case 'p':
- X case 'P':
- X strcat(result, possessive[Genderof(player)]);
- X break;
- X case 'o':
- X case 'O':
- X strcat(result, objective[Genderof(player)]);
- X break;
- X case 'n':
- X case 'N':
- X strcat(result, db[player].name);
- X break;
- X default:
- X *result = *str;
- X result[1] = '\0';
- X break;
- X }
- X if(isupper(c) && islower(*result)) {
- X *result = toupper(*result);
- X }
- X
- X result += strlen(result);
- X str++;
- X }
- X } else {
- X *result++ = *str++;
- X }
- X }
- X *result = '\0';
- X}
- X
- X#endif /* GENDER */
- END_OF_FILE
- if test 6557 -ne `wc -c <'predicates.c'`; then
- echo shar: \"'predicates.c'\" unpacked with wrong size!
- fi
- # end of 'predicates.c'
- fi
- if test -f 'speech.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'speech.c'\"
- else
- echo shar: Extracting \"'speech.c'\" \(5423 characters\)
- sed "s/^X//" >'speech.c' <<'END_OF_FILE'
- X#include "copyright.h"
- X
- X/* Commands which involve speaking */
- X
- X#include "db.h"
- X#include "interface.h"
- X#include "match.h"
- X#include "config.h"
- X#include "externs.h"
- X
- X/* this function is a kludge for regenerating messages split by '=' */
- Xconst char *reconstruct_message(const char *arg1, const char *arg2)
- X{
- X static char buf[BUFFER_LEN];
- X
- X if(arg2 && *arg2) {
- X strcpy(buf, arg1);
- X strcat(buf, " = ");
- X strcat(buf, arg2);
- X return buf;
- X } else {
- X return arg1;
- X }
- X}
- X
- Xvoid do_say(dbref player, const char *arg1, const char *arg2)
- X{
- X dbref loc;
- X const char *message;
- X char buf[BUFFER_LEN];
- X
- X if((loc = getloc(player)) == NOTHING) return;
- X
- X message = reconstruct_message(arg1, arg2);
- X
- X /* notify everybody */
- X sprintf(buf, "You say \"%s\"", message);
- X notify(player, buf);
- X sprintf(buf, "%s says \"%s\"", db[player].name, message);
- X notify_except(db[loc].contents, player, buf);
- X}
- X
- Xvoid do_whisper(dbref player, const char *arg1, const char *arg2)
- X{
- X#ifndef QUIET_WHISPER
- X dbref loc;
- X#endif QUIET_WHISPER
- X dbref who;
- X char buf[BUFFER_LEN];
- X char *det;
- X int result;
- X
- X init_match(player, arg1, TYPE_PLAYER);
- X match_neighbor();
- X match_me();
- X if(Wizard(player)) {
- X match_absolute();
- X match_player();
- X }
- X switch(who = match_result()) {
- X case NOTHING:
- X notify(player, "Whisper to whom?");
- X break;
- X case AMBIGUOUS:
- X notify(player, "I don't know who you mean!");
- X break;
- X default:
- X if (Typeof(who) == TYPE_PLAYER) {
- X sprintf(buf, "%s whispers \"%s\"", db[player].name, arg2);
- X if (notify(who, buf)) {
- X sprintf(buf, "You whisper \"%s\" to %s.", arg2, db[who].name);
- X notify(player, buf);
- X#ifndef QUIET_WHISPER
- X sprintf(buf, "%s whispers something to %s.",
- X db[player].name, db[who].name);
- X if((loc = getloc(player)) != NOTHING) {
- X notify_except2(db[loc].contents, player, who, buf);
- X }
- X#endif /* QUIET_WHISPER */
- X }
- X else
- X notify(player, "That person is not connected.");
- X } else {
- X if (string_prefix (db[who].name, "a ") ||
- X string_prefix (db[who].name, "an ") ||
- X string_prefix (db[who].name, "the ") ||
- X string_prefix (db[who].name, "some ")) {
- X det = "";
- X } else if (lookup_player (db[who].name) != NOTHING) {
- X det = "the thing called ";
- X } else {
- X det = "the ";
- X }
- X sprintf(buf, "You feel silly about whispering to %s%s.",
- X det, db[who].name);
- X notify(player, buf);
- X }
- X break;
- X }
- X}
- X
- Xvoid do_pose(dbref player, const char *arg1, const char *arg2)
- X{
- X dbref loc;
- X const char *message;
- X char buf[BUFFER_LEN];
- X
- X if((loc = getloc(player)) == NOTHING) return;
- X
- X message = reconstruct_message(arg1, arg2);
- X
- X /* notify everybody */
- X sprintf(buf, "%s %s", db[player].name, message);
- X notify_except(db[loc].contents, NOTHING, buf);
- X}
- X
- Xvoid do_wall(dbref player, const char *arg1, const char *arg2)
- X{
- X dbref i;
- X const char *message;
- X char buf[512];
- X
- X message = reconstruct_message(arg1, arg2);
- X if(Wizard(player)) {
- X writelog("WALL from %s(%d): %s\n",
- X db[player].name, player, message);
- X sprintf(buf, "%s shouts \"%s\"", db[player].name, message);
- X for(i = 0; i < db_top; i++) {
- X if(Typeof(i) == TYPE_PLAYER) {
- X notify(i, buf);
- X }
- X }
- X } else {
- X notify(player, "But what do you want to do with the wall?");
- X }
- X}
- X
- Xvoid do_gripe(dbref player, const char *arg1, const char *arg2)
- X{
- X dbref loc;
- X const char *message;
- X
- X loc = db[player].location;
- X message = reconstruct_message(arg1, arg2);
- X writelog("GRIPE from %s(%d) in %s(%d): %s\n",
- X db[player].name, player,
- X db[loc].name, loc,
- X message);
- X fflush(stderr);
- X
- X#ifdef GOD_PRIV
- X /* try telling GOD about it */
- X if (!Flag(GOD,HAVEN)) {
- X char buf[BUFFER_LEN];
- X sprintf(buf, "%s gripes: \"%s\"",
- X unparse_object(GOD, player), message);
- X notify(GOD, buf);
- X }
- X#endif GOD_PRIV
- X
- X notify(player, "Your complaint has been duly noted.");
- X}
- X
- X/* doesn't really belong here, but I couldn't figure out where else */
- Xvoid do_page(dbref player, const char *arg1, const char *arg2)
- X{
- X char buf[BUFFER_LEN];
- X dbref target;
- X int result;
- X
- X if(!payfor(player, PAGE_COST)) {
- X notify(player, "You don't have enough pennies.");
- X } else if((target = lookup_player(arg1)) == NOTHING) {
- X notify(player, "I don't recognize that name.");
- X } else if (db[target].flags & HAVEN) {
- X notify(player, "That player is not accepting pages.");
- X } else if (arg2 && *arg2) {
- X sprintf(buf, "%s pages: %s", db[player].name, arg2);
- X result = notify(target, buf);
- X if (result)
- X notify(player, "Your message has been sent.");
- X else
- X notify(player, "That person is not connected.");
- X } else {
- X sprintf(buf, "You sense that %s is looking for you in %s.",
- X db[player].name, db[db[player].location].name);
- X result = notify(target, buf);
- X if (result)
- X notify(player, "Your message has been sent.");
- X else
- X notify(player, "That person is not connected.");
- X }
- X}
- X
- Xvoid notify_except(dbref first, dbref exception, const char *msg)
- X{
- X DOLIST (first, first) {
- X if ((db[first].flags & TYPE_MASK) == TYPE_PLAYER
- X && first != exception) {
- X notify (first, msg);
- X }
- X }
- X}
- X
- Xvoid notify_except2(dbref first, dbref exc1, dbref exc2, const char *msg)
- X{
- X DOLIST (first, first) {
- X if ((db[first].flags & TYPE_MASK) == TYPE_PLAYER
- X && first != exc1
- X && first != exc2) {
- X notify (first, msg);
- X }
- X }
- X}
- END_OF_FILE
- if test 5423 -ne `wc -c <'speech.c'`; then
- echo shar: \"'speech.c'\" unpacked with wrong size!
- fi
- # end of 'speech.c'
- fi
- echo shar: End of archive 9 \(of 10\).
- cp /dev/null ark9isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 10 archives.
- echo ">>> now type 'sh joinspl.sh'"
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-